#ifndef AVALON_MYSQLUIDDATASTORE_HPP
#define AVALON_MYSQLUIDDATASTORE_HPP
#include <boost/thread/mutex.hpp>
#include "Avalon/Network/Network.hpp"
#include "Avalon/UidService/UidDataStore.hpp"

namespace mysqlpp {
  class Connection;
}

namespace Avalon {
namespace UidService {

  /*! \class MySqlUidDataStore
   *  \brief Implements the UidDataStore using MySQL.
   *  \author Kamal Mansouri <kranar@hotmail.com>
   */
  class MySqlUidDataStore : public UidDataStore {
    public:

      //! Constructs a MySqlUidDataStore.
      /*!
        \param address The IP address of the MySQL database to connect to.
        \param schema The name of the schema.
        \param username The username to connect as.
        \param password The password associated with the <i>username</i>.
      */
      MySqlUidDataStore(const Network::IpAddress& address,
        const std::string& schema, const std::string& username,
        const std::string& password);

      virtual ~MySqlUidDataStore();

      virtual long long GetNextUid();

      virtual long long Reserve(long long size);

      virtual void Connect();

      virtual bool IsConnected() const;

      virtual void Close();

      virtual boost::signals2::connection ConnectClosedSignal(
        const ClosedSignal::slot_type& slot) const;

      virtual boost::signals2::connection ConnectClosedSignal(
        const ClosedSignal::slot_type& slot, Out<bool> isConnected) const;

    private:
      mutable boost::mutex m_mutex;
      Network::IpAddress m_address;
      std::string m_schema;
      std::string m_username;
      std::string m_password;
      boost::scoped_ptr<mysqlpp::Connection> m_databaseConnection;
      bool m_isConnected;
      long long m_nextUid;
      mutable ClosedSignal m_closedSignal;

      long long LockedGetNextUid();
  };
}
}

#endif // AVALON_MYSQLUIDDATASTORE_HPP
